/**
 *    Copyright (C) 2008  Victor Smirnov <aist11@gmail.com>
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License along
 *    with this program; if not, write to the Free Software Foundation, Inc.,
 *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *    See LICENSE.exceptions in the root folder of this project for possible
 *    exceptions
 *
 */

#ifndef _CUBEFS_CORE_TOOLS_TYPES_TYPEHASH_HPP
#define	_CUBEFS_CORE_TOOLS_TYPES_TYPEHASH_HPP

#include <cubefs/core/tools/types/typelist.hpp>
#include <cubefs/core/tools/bitmap.hpp>
#include <cubefs/api/types.hpp>

namespace cubefs    {
namespace tools     {


template <typename Type>
class TypeHash {
public:
    static const UInt Value = Type::kHashCode;
};

template <UInt HashValue>
class HashCode{};

template <UInt HashValue>
class TypeHash<HashCode<HashValue> > {
public:
    static const UInt Value = HashValue;
};


template <typename List> struct ListHash;

template <typename Head, typename Tail>
struct ListHash<TypeList<Head, Tail> > {
    static const UInt Value = CSHR<UInt, TypeHash<Head>::Value, 1>::Value ^ ListHash<Tail>::Value;
};

template <>
struct ListHash<NullType> {
    static const UInt Value = 0;
};

static Int GetListHash(const Int* list, Int size) {
    Int value = 0;
    for (Int c = 0; c < size; c++) {
        std::cout<<"List: "<<list[c]<<" "<<value<<std::endl;
        value = CShr(value, 2) ^ list[c];
    }
    return value;
}

inline Int PtrToInt(const void *ptr) {
    const Long ptr_value = (Long)ptr;
    return (Int) ptr_value & 0xFFFFFFFF;
}

template <typename Type>
Int Hash(Type *ptr) {
    return CShr(PtrToInt(ptr), 2) ^ TypeHash<Type>::Value;
}



template <>
class TypeHash<Byte> {
public:
    static const UInt Value = 1;
};

template <>
class TypeHash<Short> {
public:
    static const UInt Value = 2;
};

template <>
class TypeHash<Int> {
public:
    static const UInt Value = 3;
};

template <>
class TypeHash<Long> {
public:
    static const UInt Value = 4;
};

template <>
class TypeHash<BigInt> {
public:
    static const UInt Value = 5;
};


template <>
class TypeHash<UByte> {
public:
    static const UInt Value = 11;
};

template <>
class TypeHash<UShort> {
public:
    static const UInt Value = 12;
};

template <>
class TypeHash<UInt> {
public:
    static const UInt Value = 13;
};

//template <>
//class TypeHash<ULong> {
//public:
//    static const UInt Value = 14;
//};

//template <>
//class TypeHash<UBigInt> {
//public:
//    static const UInt Value = 15;
//};


}
}

#endif	/* _CUBEFS_CORE_TOOLS_TYPES_HIERARCHY_HPP */

